﻿using Magicodes.ExporterAndImporter.Excel;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NP.BPMReportPlatform.Common;
using NP.BPMReportPlatform.Contract.Dtos;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.RecurringJobs;
using NP.Enterprise.Utils.Http;
using NPOI.HSSF.Util;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using static NP.BPMReportPlatform.Performance.Dto.PerformanceDto;
using static NP.BPMReportPlatform.RecurringJobs.Dto.SFPerformDto.SFFormTitleResponse;
using static NP.BPMReportPlatform.RecurringJobs.Dto.SFPerformDto.SFToDoResponse;
using static NPOI.HSSF.Util.HSSFColor;

namespace NP.BPMReportPlatform.Performance
{
    /// <summary>
    /// 员工绩效考核接口
    /// </summary>
    public class PerformanceService : BPMReportPlatformAppService, IPerformanceService
    {
        #region Variables

        private readonly SqlSugarClient _db;
        private readonly SqlSugarClient _dbPlatform;
        private readonly INPRestHttpHelper _nPRestHttp;
        private readonly string _esbSAPUrl;
        private readonly ICommonService _commonService;
        private readonly IExcelImporter _importer;
        ISFPerformanceSyncJob _sFPerformanceSyncJob;

        #endregion

        #region Constructor

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sqlSugarAppService"></param>
        public PerformanceService(ISqlSugarAppService sqlSugarAppService,
            INPRestHttpHelper nPRestHttp, IConfiguration configuration, ICommonService commonService, IExcelImporter importer,
            ISFPerformanceSyncJob sFPerformanceSyncJob)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _nPRestHttp = nPRestHttp;
            _esbSAPUrl = configuration["Nippon:ESB:SYQ_ESB_ERPHR_API"];
            _commonService = commonService;
            _importer = importer;
            _sFPerformanceSyncJob = sFPerformanceSyncJob;

        }

        #endregion

        /// <summary>
        /// 绩效待办
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<GetPerformanceResultOutput>> GetPerformanceToDo(GetPerformanceResultInput input)
        {
            RefAsync<int> totalCount = 0;
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;
            var listQueryable = new List<GetPerformanceResultOutput>();
            // 权限过滤（审批人看自己的单子，可以进行评分；绩效考核人或者HRBP可以看到管辖内的，可以进行催办）
            var role = getPerformanceUserRoles(input.CategoryId ?? 0);

            listQueryable = await _db.Queryable<PerformanceEntity>()
                    .WhereIF(!input.KeyWord.IsNullOrEmpty(), t => t.SubjectId.Contains(input.KeyWord) || t.SubjectName.Contains(input.KeyWord))
                    .WhereIF(!input.KeyWord2.IsNullOrEmpty(), t => t.WorkNumber.Contains(input.KeyWord2) || t.UserName.Contains(input.KeyWord2))
                    .WhereIF(!input.FormTitle.IsNullOrEmpty(), t => t.FormTitle.Contains(input.FormTitle))
                    .WhereIF(!input.TodoEntryName.IsNullOrEmpty(), t => t.TodoEntryName.Contains(input.TodoEntryName))
                    .WhereIF(input.CategoryId != null, t => t.CategoryId == input.CategoryId)
                    .WhereIF(input.Status != null, t => t.ApproveResult == input.Status)
                    .WhereIF(input.Status == 4, t => currentWorkNumber == t.WorkNumber) // 查询已办，只看审批人的
                    .WhereIF(!role.Item1, t => t.WorkNumber == currentWorkNumber || role.Item2.Contains(t.SubjectId) || t.SubjectId == currentWorkNumber)
                    .OrderBy(t => t.LastModifiedDateTime, OrderByType.Desc)
                .Select(t => new GetPerformanceResultOutput()
                {
                }).ToPageListAsync(input.PageIndex, input.PageSize, totalCount);

            listQueryable.ForEach(t =>
            {
                t.IsCanScope = t.WorkNumber == currentWorkNumber;
                t.IsCanUrging = t.WorkNumber != currentWorkNumber && (role.Item1 || role.Item2.Contains(t.SubjectId) || t.SubjectId == currentWorkNumber);
            });

            //返回结果
            return new PagedResultDto<GetPerformanceResultOutput>()
            {
                TotalCount = totalCount,
                Items = listQueryable
            };
        }

        /// <summary>
        /// 提交
        /// </summary>
        /// <param name="entity">数据</param>
        public async Task<string> Submit(SubmitScopeDto entity)
        {
            // 推送评分
            var businessData = await _db.Queryable<PerformFormDataEntity>().Where(t => t.TodoEntryId == entity.ToDoEntryId).FirstAsync();
            if (businessData == null || string.IsNullOrEmpty(businessData.FormData))
            {
                throw new Exception("未找到对应业务数据");
            }

            // 先暂存
            var savedata = _db.Queryable<PerformFormKeyDataEntity>().Where(t => t.TodoEntryId == entity.ToDoEntryId).First();
            if (savedata == null)
            {
                savedata = new PerformFormKeyDataEntity()
                {
                    TodoEntryId = entity.ToDoEntryId,
                    FormKeyData = JsonConvert.SerializeObject(entity.Scopes),
                    Record1 = entity.Record1
                };
                _db.Insertable(savedata).ExecuteCommand();
            }
            else
            {
                savedata.FormKeyData = JsonConvert.SerializeObject(entity.Scopes);
                savedata.Record1 = entity.Record1;
                _db.Updateable(savedata).ExecuteCommand();
            }

            if (entity.Status == 0)
            {
                return "暂存成功!";
            }

            Sections sections = JsonConvert.DeserializeObject<Sections>(businessData.FormData);
            // 业务目标
            sections.objectiveSections.results.ForEach(section =>
            {
                section.objectives.results.ForEach(objective =>
                objective.customElement.results.ForEach(element =>
                {
                    element.value = entity.Scopes.Where(t => t.scopeKey == element.valueKey).FirstOrDefault()?.scope;
                }));
            });
            // 价值观
            sections.competencySections.results[0].competencies.results.ForEach(objective =>
            {
                objective.customElement.results.ForEach(element =>
                {
                    element.value = entity.Scopes.Where(t => t.scopeKey == element.valueKey).FirstOrDefault()?.scope;
                });
            });

            // 综合评价
            sections.customSections.results[0]?.customElement?.results?.ForEach(element =>
            {
                element.value = entity.Scopes.Where(t => t.scopeKey == element.valueKey).FirstOrDefault()?.scope;
            });
            // 结果推送
            string token = string.Empty;
            PerformanceEntity data = null;
            // 员工确认
            if (entity.Status == 4)
            {
                data = _sFPerformanceSyncJob.SuggestScope(sections, businessData.TodoEntryId, out token);
            }
            else
            {
                data = _sFPerformanceSyncJob.SaveScope(sections, businessData.TodoEntryId, out token);
            }

            if (data.ApproveResult == 4)
            {
                if (entity.Status == 1 || entity.Status == 4)
                {
                    await _sFPerformanceSyncJob.ApproveNext(data, token);
                }
                else
                {
                    data.ApproveMessage = "已退回";
                    await _sFPerformanceSyncJob.ApprovePrev(data, token);
                }
                _db.Updateable(data).UpdateColumns(t => new { t.ApproveMessage }).ExecuteCommand();
                if (!string.IsNullOrEmpty(data.ApproveMessage) && data.ApproveMessage != "已退回")
                {
                    return data.ApproveMessage;
                }
            }
            else
            {
                if (data.ApproveMessage.Contains("You do not have permission"))
                {
                    data.ApproveMessage = "由于有另一位审批人同时提交评分，请先点击暂存并关闭，待收到下一封待办邮件后进行评分并提交（此次评分等内容会自动保存）。";
                }
                return data.ApproveMessage;
            }

            return "成功";

        }

        /// <summary>
        /// 检查待办当前状态
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> CheckToDoData(int id)
        {
            return await _sFPerformanceSyncJob.CheckToDoData(id);
        }

        /// <summary>
        /// 获取表单明细
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<object> GetDetailById(int id)
        {
            // 判断待办是否存在
            var performance = await _db.Queryable<PerformanceEntity>().FirstAsync(t => t.TodoEntryId == id);
            var orgName = _dbPlatform.Queryable<Users>().First(t => t.WorkNumber == performance.SubjectId)?.FullPathText;
            var applyJob = _dbPlatform.Queryable<UserExtension>().First(t => t.Sapemployeeid == performance.SubjectId)?.Employeepostname;
            var formData = await _db.Queryable<PerformFormDataEntity>().FirstAsync(t => t.TodoEntryId == id);
            var formKeyData = await _db.Queryable<PerformFormKeyDataEntity>().FirstAsync(t => t.TodoEntryId == id);
            var steps = _db.Queryable<PerformStepEntity>().Where(t => t.FormDataId == performance.FormDataId).OrderBy(t => t.StepNumber).ToList();
            return new
            {
                performance,
                orgName,
                applyJob,
                formData,
                formKeyData,
                steps
            };
        }

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<MemoryStream> ExportResultDetailAsync(PerformHistoryExportDto data)
        {
            var fs = File.OpenRead(Environment.CurrentDirectory + $"/wwwroot/excel/绩效评估-{data.formData.Template}.xlsx");
            IWorkbook workbook = new XSSFWorkbook(fs);
            ISheet sheet = workbook.GetSheetAt(0);
            #region // 边框样式

            // 表头样式
            ICellStyle titleStyle = workbook.CreateCellStyle();
            titleStyle.BorderLeft = BorderStyle.Thin;
            titleStyle.BorderRight = BorderStyle.Thin;
            titleStyle.BorderTop = BorderStyle.Thin;
            titleStyle.BorderBottom = BorderStyle.Thin;
            titleStyle.FillForegroundColor = HSSFColor.LightYellow.Index;
            titleStyle.FillPattern = FillPattern.SolidForeground;
            IFont f = workbook.CreateFont();
            f.Boldweight = (short)FontBoldWeight.Bold;
            titleStyle.SetFont(f);

            // 内容样式
            ICellStyle contentStyle = workbook.CreateCellStyle();
            contentStyle.BorderLeft = BorderStyle.Thin;
            contentStyle.BorderRight = BorderStyle.Thin;
            contentStyle.BorderTop = BorderStyle.Thin;
            contentStyle.BorderBottom = BorderStyle.Thin;
            #endregion

            // 基本信息
            sheet.GetRow(0).GetCell(1).SetCellValue(data.formData.FormTitle);
            sheet.GetRow(1).GetCell(1).SetCellValue(data.formData.SubjectId);
            sheet.GetRow(1).GetCell(3).SetCellValue(data.formData.SubjectName);
            sheet.GetRow(2).GetCell(1).SetCellValue(data.formData.OrgName);
            sheet.GetRow(2).GetCell(3).SetCellValue(data.formData.ApplyerJob);
            sheet.GetRow(3).GetCell(1).SetCellValue(data.formData.LastLevel);
            // 第一部分：组织目标
            sheet.GetRow(6).GetCell(0).SetCellValue(data.businessData.Record1);
            int startrow = 9;
            IRow row = null;
            ICell cell = null;
            List<string> columnkey = new List<string>();
            if (data.Columns.SecondColumn != null && data.Columns.SecondColumn.Count() > 0)
            {
                startrow = AddColumnData(startrow, sheet, data.Columns.SecondColumn, data.businessData.SecondData, titleStyle, contentStyle);
            }

            if (data.Columns.ThirdColumn != null && data.Columns.ThirdColumn.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.ThirdColumn, data.businessData.ThirdData, titleStyle, contentStyle);
            }
            if (data.Columns.ThirdColumn1 != null && data.Columns.ThirdColumn1.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.ThirdColumn1, data.businessData.ThirdData1, titleStyle, contentStyle);
            }
            if (data.Columns.ThirdColumn2 != null && data.Columns.ThirdColumn2.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.ThirdColumn2, data.businessData.ThirdData2, titleStyle, contentStyle);
            }
            if (data.Columns.FourColumn != null && data.Columns.FourColumn.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.FourColumn, data.businessData.FourData, titleStyle, contentStyle);
            }
            if (data.Columns.FiveColumn != null && data.Columns.FiveColumn.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.FiveColumn, data.businessData.FiveData, titleStyle, contentStyle);
            }
            if (data.Columns.TotalColumn != null && data.Columns.TotalColumn.Count() > 0)
            {
                startrow = AddColumnData(startrow + 2, sheet, data.Columns.TotalColumn, data.businessData.TotalData, titleStyle, contentStyle, true);
            }

            MemoryStream memoryStream = new MemoryStream();
            workbook.Write(memoryStream);
            workbook.Close();
            return memoryStream;
        }

        private int AddColumnData(int startrow, ISheet sheet, List<ColumnCellDto> colunms, List<JObject> data, ICellStyle titleStyle, ICellStyle contentStyle, bool istotal = false)
        {
            List<string> columnkey = new List<string>();
            IRow row = sheet.GetRow(startrow);
            ICell cell = null;
            // 第一行，表头
            if (!istotal)
            {
                for (int i = 0; i < colunms.Count(); i++)
                {
                    var column = colunms[i];
                    cell = row.CreateCell(i);
                    cell.SetCellValue(column.title);
                    cell.CellStyle = titleStyle;
                    columnkey.Add(column.field);
                }
            }
            else
            {
                columnkey = new List<string>() { "StepName", "UserRole", "UserName", "Scope", "ScopeLevel", "ScopeRemark" };
            }

            startrow++;
            // 复制行项目
            SetNewRow(startrow, sheet, data.Count);
            foreach (var item in data)
            {
                row = sheet.GetRow(startrow++);
                for (int i = 0; i < columnkey.Count(); i++)
                {
                    cell = row.CreateCell(i);
                    string value = item.ContainsKey(columnkey[i]) ? item[columnkey[i]].ToString().Replace("<p>", "").Replace("</p>", "") : "";
                    cell.SetCellValue(value);
                    cell.CellStyle = contentStyle;
                }
            }
            return startrow;
        }

        /// <summary>
        /// 获取用户权限
        /// </summary>
        /// <returns></returns>
        private Tuple<bool, List<string>> getPerformanceUserRoles(int category)
        {
            // 权限过滤
            var currentWorkNumber = CurrentUser != null && CurrentUser.UserName != null ? CurrentUser.UserName : string.Empty;
            var userCodes = _commonService.GetUserByRoleFilter(currentWorkNumber, category == 0 ? RelationshipTypeEnum.HRBPPerformance : RelationshipTypeEnum.HRBPHead);
            userCodes = userCodes != null && userCodes.Count > 0 ? userCodes : new List<string>() { "-1" };
            bool isAdmin = userCodes.Contains("9999999999");
            return new Tuple<bool, List<string>>(isAdmin, userCodes);

        }

        private void SetNewRow(int startrows, ISheet sheet, int count)
        {
            if (count == 1)
            {
                return;
            }
            var rowSource = sheet.GetRow(startrows);
            var rowStyle = rowSource.RowStyle;//获取当前行样式
                                              //插入行
            sheet.ShiftRows(startrows, sheet.LastRowNum, count - 1);
            for (int i = startrows; i < startrows + count - 1; i++)
            {
                var rowInsert = sheet.CreateRow(i);
                if (rowStyle != null)
                    rowInsert.RowStyle = rowStyle;
                rowInsert.Height = rowSource.Height;

                for (int col = 0; col < rowSource.LastCellNum; col++)
                {
                    var cellsource = rowSource.GetCell(col);
                    var cellInsert = rowInsert.CreateCell(col);
                    var cellStyle = cellsource.CellStyle;
                    //设置单元格样式　　　　
                    if (cellStyle != null)
                        cellInsert.CellStyle = cellsource.CellStyle;
                }
            }
        }
    }
}